package br.com.megasena.infraestrutura;

import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import org.apache.log4j.Logger;

public abstract class GenericJpaDAO<T extends Serializable> implements GenericDAO<T, Serializable>{
	
	private static Logger logger = Logger.getLogger(GenericJpaDAO.class);
	private EntityManager manager = JpaFactory.create();
	
	public T load(Class<T> classToSearch,Serializable id) {
		return (T) manager.find(classToSearch, id);
	}

	@SuppressWarnings("unchecked")
	public  T getPojoById(Class<T> classToSearch, Serializable id) throws PersistenceException {
		logger.info("buscando " + classToSearch + " com o id: " + id);
		//getEntityManager().getTransaction().begin();
		Serializable toReturn = (T) manager.find(classToSearch, id);
		//getEntityManager().getTransaction().commit();
		return (T) toReturn;
		
	}
		
	public void saveOrUpdatePojo(Serializable pojo) throws PersistenceException{
		try {
			logger.info("Salvando " + pojo);
			manager.getTransaction().begin();
			manager.persist(pojo);
			manager.getTransaction().commit();
				
		} catch (PersistenceException ex) {
			logger.info("Desfazendo persistencia de " + pojo + "Erro: " + ex);
			manager.getTransaction().rollback();
			throw new PersistenceException(ex);
		} catch (RuntimeException ex) {
 			throw ex;
		}
	}
	
	public void savePojo(Serializable pojo) throws PersistenceException{
		try {
			logger.info("Salvando " + pojo);
			manager.getTransaction().begin();
			manager.persist(pojo);
			manager.getTransaction().commit();
				
		} catch (PersistenceException ex) {
			logger.info("Desfazendo persistencia de " + pojo + "Erro: " + ex);
			manager.getTransaction().rollback();
			throw new PersistenceException(ex);
		} catch (RuntimeException ex) {
 			throw ex;
		}
	}
	
	public void updatePojo(Serializable pojo) throws PersistenceException{
		try {
			logger.info("Salvando " + pojo);
			manager.getTransaction().begin();
			manager.merge(pojo);
			manager.getTransaction().commit();
				
		} catch (PersistenceException ex) {
			logger.info("Desfazendo persistencia de " + pojo + "Erro: " + ex);
			manager.getTransaction().rollback();
			throw new PersistenceException(ex);
		} catch (RuntimeException ex) {
 			throw ex;
		}
	}
	
	public void removePojo(Serializable pojo) throws PersistenceException {
		
		try {
			logger.info("Removendo " + pojo);
			manager.getTransaction().begin();
			manager.remove(pojo);
			manager.getTransaction().commit();
				
		} catch (PersistenceException ex) {
			logger.info("Desfazendo remoção de " + pojo);
			manager.getTransaction().rollback();
			throw new PersistenceException(ex);
		} catch (RuntimeException ex) {
 			throw ex;
		}
	}
	
	@SuppressWarnings("unchecked")
	public T getPurePojo(String query, Object...params) throws PersistenceException {
		Query qr = manager.createQuery(query);
		for (int i = 1; i <= params.length; i++) {
			qr.setParameter(i, params[i-1]);
		}
		Serializable toReturn = (T) qr.getSingleResult();
		return (T) toReturn;
		
	}
	
	public List<T> getListPojos(Class<T> classToCast, String query, Object...params) throws PersistenceException {
		Query qr = manager.createQuery(query);
		for (int i = 1; i <= params.length; i++) {
			qr.setParameter(i, params[i-1]);
		}
		@SuppressWarnings("unchecked")
		List<T> toReturn = qr.getResultList();
		return toReturn;
		
	}
}
